package driver

import (
	"slices"
	"sync"
)

// memoryTags 标签集合, 用于快速查找带有相同标签的缓存项
//   - 同时支持存储两种映射关系:
//   - tag到keys 集合(tag=>[]keys), 此时key为缓存tag，items元素为key集合
//   - key到tags 集合(key=>[]tags), 此时key为缓存key，items元素为tag集合
type memoryTags struct {
	// map[tag]=> map实现的集合 []keys
	// map[key]=> map实现的集合 []tags
	items      map[string]map[string]struct{}
	emptySlice []string
	mu         sync.RWMutex
}

func newMemoryTags() *memoryTags {
	return &memoryTags{
		items:      make(map[string]map[string]struct{}),
		emptySlice: []string{},
	}
}

func (t *memoryTags) Size() int {
	t.mu.RLock()
	c := len(t.items)
	t.mu.RUnlock()
	return c
}

func (t *memoryTags) Has(key string) bool {
	if key == "" {
		return false
	}
	t.mu.RLock()
	defer t.mu.RUnlock()
	_, ok := t.items[key]
	return ok
}

func (t *memoryTags) GetKeys() []string {
	t.mu.RLock()
	defer t.mu.RUnlock()
	if len(t.items) == 0 {
		return t.emptySlice[:0]
	}
	keys := make([]string, 0, len(t.items))
	for v := range t.items {
		keys = append(keys, v)
	}
	// 排序返回结果
	slices.Sort(keys)
	return keys
}
func (t *memoryTags) GetItems(key string) []string {
	if key == "" {
		return t.emptySlice[:0]
	}
	t.mu.Lock()
	defer t.mu.Unlock()
	if _, ok := t.items[key]; !ok || len(t.items[key]) == 0 {
		return t.emptySlice[:0]
	}
	items := make([]string, 0, len(t.items[key]))
	for v := range t.items[key] {
		items = append(items, v)
	}
	// 排序返回结果
	slices.Sort(items)
	return items
}
func (t *memoryTags) HasKV(key, item string) bool {
	if key == "" || item == "" {
		return false
	}
	t.mu.RLock()
	defer t.mu.RUnlock()
	_, ok := t.items[key]
	if !ok || len(t.items[key]) == 0 {
		return false
	}
	_, ok = t.items[key][item]
	return ok
}

func (t *memoryTags) AddKV(key string, items ...string) {
	if key == "" || len(items) == 0 {
		return
	}
	t.mu.Lock()
	defer t.mu.Unlock()
	if _, ok := t.items[key]; !ok {
		t.items[key] = make(map[string]struct{}, len(items))
	}
	for _, v := range items {
		if v != "" {
			t.items[key][v] = struct{}{}
		}
	}
}
func (t *memoryTags) Remove(key string) {
	if key == "" || len(t.items) == 0 {
		return
	}
	t.mu.Lock()
	defer t.mu.Unlock()
	if _, ok := t.items[key]; !ok {
		return
	}
	delete(t.items, key)
}
func (t *memoryTags) RemoveKV(key string, items ...string) {
	if key == "" || len(items) == 0 {
		return
	}
	t.mu.Lock()
	defer t.mu.Unlock()
	if _, ok := t.items[key]; !ok || len(t.items[key]) == 0 {
		return
	}
	for _, v := range items {
		if v != "" {
			delete(t.items[key], v)
		}
	}
}
func (t *memoryTags) Clear() {
	t.mu.Lock()
	t.items = make(map[string]map[string]struct{})
	t.mu.Unlock()
}
